home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / editor / j414src.arc / IPROCXPI.C < prev    next >
C/C++ Source or Header  |  1989-10-10  |  6KB  |  280 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* NOTE WELL:
  9.  * This file is "included" into iproc.c -- it is not compiled separately!
  10.  */
  11.  
  12. #include <signal.h>
  13. #include <sgtty.h>
  14. #include "wait.h"
  15.  
  16. #define DEAD    1    /* Dead but haven't informed user yet */
  17. #define STOPPED    2    /* Job stopped */
  18. #define RUNNING    3    /* Just running */
  19. #define NEW    4    /* This process is brand new */
  20.  
  21. /* If process is dead, flags says how. */
  22. #define EXITED    1
  23. #define KILLED    2
  24.  
  25. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_toproc == -1)
  26. #define makedead(p)    { proc_state((p)) = DEAD; }
  27.  
  28. #define proc_buf(p)    ((p)->p_buffer->b_name)
  29. #define proc_cmd(p)    ((p)->p_name)
  30. #define proc_state(p)    ((p)->p_state)
  31.  
  32. private Process    *procs = 0;
  33.  
  34. File    *ProcInput;
  35. int    ProcOutput,
  36.     kbd_pid = 0,
  37.     NumProcs = 0;
  38.  
  39. private Process *
  40. proc_pid(pid)
  41. int    pid;
  42. {
  43.     register Process    *p;
  44.  
  45.     for (p = procs; p != 0; p = p->p_next)
  46.         if (p->p_portpid == pid)
  47.             break;
  48.  
  49.     return p;
  50. }
  51.  
  52. void
  53. read_proc(pid, nbytes)
  54. int    pid;
  55. register int    nbytes;
  56. {
  57.     register Process    *p;
  58.     int    n;
  59.     char    ibuf[512];
  60.  
  61.     if ((p = proc_pid(pid)) == 0) {
  62.         writef("\riproc: unknown pid (%d)", pid);
  63.         return;
  64.     }
  65.  
  66.     if (proc_state(p) == NEW) {
  67.         int    rpid;
  68.         /* pid of real child, not of portsrv */
  69.  
  70.         (void) f_readn(ProcInput, (char *) &rpid, sizeof (int));
  71.         p->p_pid = rpid;
  72.         p->p_state = RUNNING;
  73.         return;
  74.     }
  75.  
  76.     if (nbytes == EOF) {        /* okay to clean up this process */
  77.         int    status, pid;
  78.  
  79.         f_readn(ProcInput, &status, sizeof (int));
  80.         do {
  81.             pid = wait((int *) 0);
  82.             if (pid < 0)
  83.                 break;
  84.             kill_off(pid, status);
  85.         } while (pid != p->p_portpid);
  86.         proc_close(p);
  87.         makedead(p);
  88.         return;
  89.     }
  90.  
  91.     while (nbytes > 0) {
  92.         n = min((sizeof ibuf) - 1, nbytes);
  93.         f_readn(ProcInput, ibuf, n);
  94.         ibuf[n] = 0;    /* Null terminate for convenience */
  95.         nbytes -= n;
  96.         proc_rec(p, ibuf);
  97.     }
  98. }
  99.  
  100. void
  101. ProcKill()
  102. {
  103.     proc_kill(curbuf->b_process, SIGKILL);
  104. }
  105.  
  106. void
  107. ProcInt()
  108. {
  109.     proc_kill(curbuf->b_process, SIGINT);
  110. }
  111.  
  112. void
  113. ProcQuit()
  114. {
  115.     proc_kill(curbuf->b_process, SIGQUIT);
  116. }
  117.  
  118. private void
  119. proc_close(p)
  120. Process    *p;
  121. {
  122.     if (p->p_toproc >= 0) {
  123.         (void) close(p->p_toproc);
  124.         p->p_toproc = -1;    /* writes will fail */
  125.         NumProcs -= 1;
  126.     }
  127. }
  128.  
  129. void
  130. proc_write(p, buf, nbytes)
  131. Process    *p;
  132. char    *buf;
  133. size_t    nbytes;
  134. {
  135.     (void) write(p->p_toproc, buf, nbytes);
  136. }
  137.  
  138.  
  139. #ifdef    STDARGS
  140.     private void
  141. proc_strt(char *bufname, int clobber, ...)
  142. #else
  143.     private /*VARARGS3*/ void
  144. proc_strt(bufname, clobber, va_alist)
  145.     char    *bufname;
  146.     int    clobber;
  147.     va_dcl
  148. #endif
  149. {
  150.     Window    *owind = curwind;
  151.     int    toproc[2],
  152.         pid;
  153.     Process    *newp;
  154.     Buffer    *newbuf;
  155.     char    *argv[32],
  156.         *cp,
  157.         foo[10],
  158.         cmdbuf[128];
  159.     int    i;
  160.     va_list    ap;
  161.  
  162.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  163.                    or is of type B_PROCESS */
  164.     dopipe(toproc);
  165.  
  166.     switch (pid = fork()) {
  167.     case -1:
  168.         pclose(toproc);
  169.         complain("[Fork failed.]");
  170.  
  171.     case 0:
  172.         argv[0] = "portsrv";
  173.         va_init(ap, clobber);
  174.         make_argv(&argv[1], ap);
  175.         va_end(ap);
  176.         (void) dup2(toproc[0], 0);
  177.         (void) dup2(ProcOutput, 1);
  178.         (void) dup2(ProcOutput, 2);
  179.         pclose(toproc);
  180.         execv(Portsrv, argv);
  181.         writef("execl failed\n");
  182.         _exit(1);
  183.     }
  184.  
  185.     newp = (Process *) malloc(sizeof *newp);
  186.     newp->p_next = procs;
  187.     newp->p_state = NEW;
  188.  
  189.     cmdbuf[0] = '\0';
  190.     va_init(ap, clobber);
  191.     while (cp = va_arg(ap, char *))
  192.         swritef(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
  193.     va_end(ap);
  194.     va_init(ap, clobber);
  195.     newp->p_name = copystr(cmdbuf);
  196.     procs = newp;
  197.     newp->p_portpid = pid;
  198.     newp->p_pid = -1;
  199.  
  200.     newbuf = do_select((Window *) 0, bufname);
  201.     newbuf->b_type = B_PROCESS;
  202.     newp->p_buffer = newbuf;
  203.     newbuf->b_process = newp;    /* sorta circular, eh? */
  204.     pop_wind(bufname, clobber, B_PROCESS);
  205.     ToLast();
  206.     if (!bolp())
  207.         LineInsert(1);
  208.     /* Pop_wind() after everything is set up; important!
  209.        Bindings won't work right unless newbuf->b_process is already
  210.        set up BEFORE NEWBUF is first SetBuf()'d. */
  211.     newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  212.     newp->p_dbx_mode = NO;
  213.  
  214.     newp->p_toproc = toproc[1];
  215.     newp->p_reason = 0;
  216.     NumProcs += 1;
  217.     if (NumProcs == 1)
  218.         (void) kbd_strt();
  219.     (void) close(toproc[0]);
  220.     SetWind(owind);
  221. }
  222.  
  223. void
  224. pinit()
  225. {
  226.     int    p[2];
  227.  
  228.     (void) pipe(p);
  229.     ProcInput = fd_open("process-input", F_READ|F_LOCKED, p[0],
  230.                 (char *) 0, 512);
  231.     ProcOutput = p[1];
  232.     if ((kbd_pid = fork()) == -1) {
  233.         printf("Cannot fork kbd process!\n");
  234.         finish(1);
  235.     }
  236.     if (kbd_pid == 0) {
  237.         signal(SIGINT, SIG_IGN);
  238.         signal(SIGALRM, SIG_IGN);
  239.         close(1);
  240.         dup(ProcOutput);
  241.         execl(Kbd_Proc, "kbd", 0);
  242.         write(2, "kdb exec failed\n", 16);
  243.         exit(-1);
  244.     }
  245. }
  246.  
  247. private int    kbd_state = OFF;
  248.  
  249. /* kbd_strt() and kbd_stop() return true if they changed the state
  250.    of the keyboard process.  E.g., kbd_strt() returns TRUE if the
  251.    kbd process was previously stopped.  This is so kbd starting and
  252.    stopping in pairs works - see finish() in jove.c. */
  253.  
  254. kbd_strt()
  255. {
  256.     if (kbd_state == OFF) {
  257.         kbd_state = ON;
  258.         kill(kbd_pid, SIGQUIT);
  259.         return TRUE;
  260.     }
  261.     return FALSE;
  262. }
  263.  
  264. kbd_stop()
  265. {
  266.     if (kbd_state == ON) {
  267.         kbd_state = OFF;
  268.         kill(kbd_pid, SIGQUIT);
  269.         return TRUE;
  270.     }
  271.     return FALSE;
  272. }
  273.  
  274. kbd_kill()
  275. {
  276.     if (kbd_pid != 0) {
  277.         kill(kbd_pid, SIGKILL);
  278.         kbd_pid = 0;
  279.     }
  280. }